﻿#ifdef _DEBUG
#pragma comment(lib, "..\\..\\lib\\Debug\\Utils-d.lib")
#pragma comment(lib, "..\\..\\lib\\Debug\\Elements-d.lib")
#else
#pragma comment(lib, "..\\..\\lib\\Release\\Utils.lib")
#pragma comment(lib, "..\\..\\lib\\Release\\Elements.lib")
#endif

#include "config.h"
#include <SDL/SDL.h>
#include <vector>
#include <tchar.h>
#include "Utils\\AWindow.h"
#include "Utils\\ScreenFactory.h"
#include "Utils\\ScreenManager.h"
#include "Utils\\IScreen.h"
#include "Utils\\Font.h"
#include "Elements\\Image.h"
#include "Elements\\Label.h"
#include "Elements\\PushButton.h"
#include "Elements\\CheckBox.h"
#include "Elements\\ElementManager.h"

using namespace SDL::UTILS;
using namespace SDL::ELEMENTS;

struct MainArgs : public ScreenArgs
{
public:
	int Option;

public:
	MainArgs(SDL_Surface* _surface, SDL_Event* _event) :
		ScreenArgs(_surface, _event), Option(0) { }

	virtual ~MainArgs() {}
};

Font* arial = NULL;

class MainScreen : public IScreen
{
private:
	Image m_background;
	Label m_moi;
	PushButton m_pbQuit;
	PushButton m_pbBig;
	PushButton m_pbBigBig;

public:
	MainScreen() : IScreen(), m_background("MainBackground.png"),
		m_moi(arial, Color()), m_pbQuit(L"Quit"),
		m_pbBig(L"Bouton avec une taille auto."),
		m_pbBigBig(L"Bouton dont j'ai choisis la taille", Rect(0, 0, 325, 250))
	{
		m_moi.SetPosition(200, 42);
		m_moi.Render(L"Cola!! ò_____ó");
		m_pbQuit.SetPosition(300, 200);
		m_pbBig.SetPosition(10, 400);
		m_pbBigBig.SetPosition(450, 300);
	}
	virtual ~MainScreen() {}


	void Draw(IArgs* _args)
	{
		MainArgs* ma = (MainArgs*)_args;
		m_background.Draw(ma->Screen);
		m_moi.Draw(ma->Screen);
		m_pbQuit.Draw(ma->Screen);
		m_pbBig.Draw(ma->Screen);
		m_pbBigBig.Draw(ma->Screen);
	}

	void Exec(IArgs* _args)
	{
		MainArgs* ma = (MainArgs*)_args;
		switch (ma->Event->type)
		{
		case SDL_KEYDOWN:
			switch (ma->Event->key.keysym.sym)
			{
			case SDLK_1: case SDLK_2: case SDLK_3:
				ma->Option = ma->Event->key.keysym.sym -  SDLK_0;
				break ;
			case SDLK_u:
				m_moi.Render(L"Cola!! ò_____ó");
				break ;
			case SDLK_n:
				m_moi.Render("Cola!! ò_____ó");
				break ;
			case SDLK_k:
				m_pbQuit.SetText(L"Poupidoupidou!!!!!!!!!!!!!!!!!");
				break ;
			case SDLK_q:
				m_pbQuit.SetText(L"Quitter");
				break ;
			}
			break ;
		}
		m_pbQuit.UpdateState();
		m_pbBig.UpdateState();
		m_pbBigBig.UpdateState();
		if (m_pbQuit.GetState() == SDL::BUTTON::STATE::CLICKED)
			ma->Option = 3;
	}

	static MainScreen* Create() { return (new MainScreen()); }
	static bool Func(ScreenManager::Element* _caller, IArgs* _args)
	{
		MainScreen* ms = (MainScreen*)_caller->Object;
		MainArgs* ma = (MainArgs*)_caller->Datas;
		if (ma->Pause == false)
			ms->Exec(_caller->Datas);
		if (ma->Hide == false)
			ms->Draw(_caller->Datas);
		return (true);
	}
};

#include "GameScreen.h"

class Window : public AWindow
{
private:
	typedef void (Window::*ScreenInteraction)();

	SDL_Event m_event;
	bool m_quit;
	ScreenManager m_screenManager;
	std::string m_currentScreen;
	std::map<std::string, ScreenInteraction> m_interactions;


public:
	Window() : AWindow(), m_quit(false)
	{
	}
	virtual ~Window() {}

	void MainScreenInteraction()
	{
		MainArgs* ma = (MainArgs*)
			m_screenManager.GetElement("MainScreen")->Datas;
		if (ma->Option == 1)
		{
			ScreenArgs args(m_screen, &m_event);
			this->InitScreen("GameScreen", (ScreenManager::MngrFunc)GameScreen::Func,
							  new ScreenArgs(m_screen, &m_event), &args);
		}
		else if (ma->Option == 3)
		{
			m_quit = true;
			ma->Option = 0;
		}
	}

	void GameScreenInteraction()
	{
		GameScreen* gs = (GameScreen*)m_screenManager["GameScreen"];
		if (gs->BackToScreen() == true)
			this->InitScreen("MainScreen", (ScreenManager::MngrFunc)MainScreen::Func,
							 new MainArgs(m_screen, &m_event));
	}

	void InitScreens()
	{
		// MainScreen
		ScreenFactory::Instance().AddCreator("MainScreen",
			(ScreenFactory::ScreenCreator)MainScreen::Create);
		m_interactions["MainScreen"] = &Window::MainScreenInteraction;
		ScreenFactory::Instance().AddCreator("GameScreen",
			(ScreenFactory::ScreenCreator)GameScreen::Create);
		m_interactions["GameScreen"] = &Window::GameScreenInteraction;
	}

	void InitScreen(std::string const& _name, ScreenManager::MngrFunc _func,
					IArgs* _datas, IArgs* _screenArgs = NULL, bool _delete = true)
	{
		m_screenManager.Clear();
		IScreen* newScreen = ScreenFactory::Instance().Create(_name, _screenArgs);
		m_screenManager.Add(_name, newScreen, _func, _datas, _delete);
		m_currentScreen = _name;
	}

	int Exec()
	{
		this->InitScreens();
		this->InitScreen("MainScreen", (ScreenManager::MngrFunc)MainScreen::Func,
						 new MainArgs(m_screen, &m_event));

		while (!m_quit)
		{
			//SDL_FillRect(m_screen, NULL, 0);

			while (SDL_PollEvent(&m_event) && !m_quit)
			{
				switch (m_event.type)
				{
				case SDL_QUIT:
					m_quit = true;
					break ;
				}
			}

			m_screenManager.Manage();
			(this->*m_interactions[m_currentScreen])();

			SDL_Flip(m_screen);
		}

		return (EXIT_SUCCESS);
	}
};

int main(int, char**)
{
	Window w;
	w.Init(SDLConfig());
	arial = new Font("C:\\Windows\\Fonts\\arial.ttf", 32, TTF_STYLE_BOLD);
	int r = w.Exec();
	delete arial;
	return (r);
}
